using MeasureAbstract.IMotionDevice;
using System;
using System.Collections.ObjectModel;
using System.Net.Sockets;
using System.Net;
using System.Text;
using System.Threading;
using System.IO.Ports;
using SixLabors.ImageSharp.Memory;
using System.Collections.Generic;
using System.Linq;
using System.Windows.Media;
using System.Windows;
using System.Threading.Tasks;
using System.IO;
using CommunityToolkit.Mvvm.ComponentModel;
using System.Windows.Controls;

namespace 苏州X暗室转台
{
    public partial class Turntable : IMotionDevice
    {


        #region
        public Turntable()
        {
            Config = new MotionDeviceConfig();
            //设置支持的通信方式
            Config.CommunicationList = new ObservableCollection<CommunicationMode>()
            {
                new CommunicationMode() {Name="TCP",Selected=true,Support=true},
                new CommunicationMode() {Name="UDP",Selected=false,Support=true},
                new CommunicationMode() {Name="UART",Selected=false,Support=true},
            };
            //设置默认通信参数
            Config.LocalIP = "10.0.0.20";
            Config.LocalPort = "8080";
            Config.DestIP = "10.0.0.100";
            Config.DestPort = "8080";
            Config.PortName = "COM1";
            Config.BandRate = "115200";

            //设置轴
            if (Config.Axes == null)
            {
                Config.Axes = new System.Collections.ObjectModel.ObservableCollection<Axis>();
            }
            Config.Axes.Clear();
            Config.Axes.Add(new Axis() { AxisID = 2, AxisName = "大方位", Accuracy = 0.01, SupportPulseOut = true });


            AnalyzeData_Func = AnalyzeData;
            Timer = new System.Timers.Timer();
            Timer.Interval = 200;
            Timer.Elapsed += Timer_Elapsed;
        }

        private int AnalyzeData(byte[] data)
        {
            //解析数据
            Config.Axes[0].CurrentPosition = double.Parse(System.Text.Encoding.ASCII.GetString(data));
            return 0;

        }

        public override string Name => "转台";

        public override string Vender => "未知";


        public override string Model => "苏州X暗室转台";

        public override string Description => "苏州客户暗室测试用";


        public override MotionDeviceConfig? Config { get; set; }



        #endregion


        System.Timers.Timer? Timer;
        private void Timer_Elapsed(object? sender, System.Timers.ElapsedEventArgs e)
        {
            //定时器

            string cmd = $"CONT1:AXIS({2}):POS:CURR?";
            SendData(System.Text.Encoding.ASCII.GetBytes(cmd));


        }


        #region 数据收发
        TcpClient? TCPClient;
        UdpClient? UdpClient;
        IPEndPoint RemoteEndPoint;
        SerialPort? SerialPort;
        Thread Thread;
        private NetworkStream stream;
        public object HeartBeatFlag = false;
        [ObservableProperty]
        private bool heartBeatEnable = true;
        public Func<byte[], int> AnalyzeData_Func;

        public override void Connect()
        {
            string SelectedCommunication = "";
            foreach (var temp in Config.CommunicationList)
            {
                if (temp.Selected)
                {
                    SelectedCommunication = temp.Name;
                }
            }
            // 创建一个CancellationTokenSource，用于取消连接操作
            CancellationTokenSource CancellationTokenSource = new CancellationTokenSource();

            if (!ConnectState)
            {
                switch (SelectedCommunication.ToUpper())
                {
                    case "TCP":
                        //TCPClient = new TcpClient();
                        //Task ConnectTask = TCPClient.ConnectAsync(Config.DestIP, int.Parse(Config.DestPort), CancellationTokenSource.Token).AsTask();

                        //// 设置连接超时时间为5秒
                        //Task TimeoutTask = Task.Delay(1000);

                        //// 使用Task.WhenAny等待连接完成或超时
                        //Task CompletedTask = await Task.WhenAny(ConnectTask, TimeoutTask);

                        //// 如果连接完成任务是连接任务，则连接成功
                        //if (CompletedTask == ConnectTask)
                        //{
                        //    stream = TCPClient.GetStream();
                        //    ConnectState = true;
                        //    //开启接收线程
                        //    while (!TCPClient.Connected) ;
                        //    Thread = new Thread(TCPReceive);
                        //    Thread.Start();
                        //    while (Thread.ThreadState != ThreadState.Running)
                        //    {

                        //    }

                        //}
                        //else
                        //{
                        //    CancellationTokenSource.Cancel();
                        //    TCPClient.Close();
                        //    ConnectState = false;
                        //    throw new Exception($"{Vender}_{Model}TCP连接超时!");
                        //}


                        TCPClient = new TcpClient();
                        IAsyncResult ConnResult = TCPClient.BeginConnect(Config.DestIP, int.Parse(Config.DestPort), null, null);

                        ConnResult.AsyncWaitHandle.WaitOne(1000, true);

                        if (!ConnResult.IsCompleted)
                        {
                            TCPClient.Close();
                            ConnectState = false;
                            throw new Exception($"{Vender}_{Model}TCP连接超时!");
                        }
                        else
                        {
                            stream = TCPClient.GetStream();
                            ConnectState = true;
                            //开启接收线程
                            Thread = new Thread(TCPReceive);
                            Thread.Start();
                            while (Thread.ThreadState != ThreadState.Running)
                            {

                            }
                        }




                        //TCPClient = new TcpClient();
                        //TCPClient.Connect(Config.DestIP, int.Parse(Config.DestPort));
                        //stream = TCPClient.GetStream();
                        //ConnectState = true;
                        ////开启接收线程
                        //while (!TCPClient.Connected) ;
                        //Thread = new Thread(TCPReceive);
                        //Thread.Start();
                        //while (Thread.ThreadState != ThreadState.Running)
                        //{

                        //}
                        break;
                    case "UDP":
                        UdpClient = new UdpClient();
                        //UdpClient.Client.Bind(new IPEndPoint(IPAddress.Parse(Config.LocalIP), int.Parse(Config.LocalPort)));
                        RemoteEndPoint = new IPEndPoint(IPAddress.Parse(Config.DestIP), int.Parse(Config.DestPort));
                        UdpClient.Connect(RemoteEndPoint);
                        ConnectState = true;
                        //开启接收线程
                        Thread = new Thread(UDPReceive);
                        Thread.Start();
                        while (Thread.ThreadState != ThreadState.Running)
                        {

                        }
                        break;
                    case "UART":
                        SerialPort = new SerialPort();
                        SerialPort.PortName = Config.PortName;
                        SerialPort.BaudRate = int.Parse(Config.BandRate);
                        SerialPort.Open();
                        ConnectState = true;
                        //开启接收线程
                        Thread = new Thread(UARTReceive);
                        Thread.Start();
                        while (Thread.ThreadState != ThreadState.Running)
                        {

                        }
                        break;
                    case "GPIB":
                        throw new NotImplementedException();
                    case "USB":
                        throw new NotImplementedException();
                    default:
                        throw new NotImplementedException();
                }
                Timer.Start();
            }
            else
            {
                //已经处于连接状态，不进行操作
            }
        }
        private void UARTReceive(object? obj)
        {
            while (true)
            {
                try
                {
                    byte[] receivedData = new byte[4];
                    if (!SerialPort.IsOpen)
                    {
                        Application.Current.Dispatcher.BeginInvoke(() => { throw new Exception($"{Vender}_{Model}串口连接断开!"); });
                        break;
                    }
                    if (SerialPort.BytesToRead > 0)
                    {
                        SerialPort.Read(receivedData, 0, SerialPort.BytesToRead);
                        //检测是否为一个完整的数据，是则进行分析，否则继续接收或丢弃


                        try
                        {
                            AnalyzeData_Func?.Invoke(receivedData);
                        }
                        catch
                        {
                            //数据错误不处理
                        }
                    }


                }
                catch (Exception e)
                {

                    DisConnect();
                    //Application.Current.Dispatcher.BeginInvoke(() => { throw new Exception($"{Vender}_{Model}串口连接断开,{e.Message}"); });
                    Application.Current.Dispatcher.BeginInvoke(() => { throw new Exception($"{Vender}_{Model}串口连接断开!"); });
                    break;
                }
            }
        }

        private void UDPReceive(object? obj)
        {
            while (true)
            {
                try
                {
                    byte[] receivedData = UdpClient.Receive(ref RemoteEndPoint);
                    try
                    {
                        AnalyzeData_Func?.Invoke(receivedData);
                    }
                    catch
                    {
                        //数据错误不处理
                    }
                }
                catch (Exception e)
                {

                    DisConnect();
                    //Application.Current.Dispatcher.BeginInvoke(() => { throw new Exception($"{Vender}_{Model}UDP连接断开,{e.Message}"); });
                    Application.Current.Dispatcher.BeginInvoke(() => { throw new Exception($"{Vender}_{Model}UDP连接断开!"); });
                    break;
                }
            }
        }

        private void TCPReceive(object? obj)
        {
            while (true)
            {
                try
                {
                    byte[] buffer = new byte[1024];
                    if (stream.CanRead)
                    {
                        int bytesRead = stream.Read(buffer, 0, buffer.Length);
                        Array.Resize(ref buffer, bytesRead);
                        try
                        {
                            AnalyzeData_Func?.Invoke(buffer);
                        }
                        catch
                        {
                            //数据错误不处理
                        }
                    }
                }
                catch (IOException e)
                {

                    DisConnect();
                    //Application.Current.Dispatcher.BeginInvoke(() => { throw new Exception($"{Vender}_{Model}TCP连接断开,{e.Message}"); });
                    Application.Current.Dispatcher.BeginInvoke(() => { throw new Exception($"{Vender}_{Model}TCP连接断开!"); });
                    break;
                }
            }
        }

        public override void DisConnect()
        {
            string SelectedCommunication = "";
            foreach (var temp in Config.CommunicationList)
            {
                if (temp.Selected)
                {
                    SelectedCommunication = temp.Name;
                }
            }
            if (ConnectState)
            {
                switch (SelectedCommunication.ToUpper())
                {
                    case "TCP":
                        stream.Close();
                        TCPClient?.Close();
                        ConnectState = false;
                        break;
                    case "UDP":
                        UdpClient?.Close();
                        ConnectState = false;
                        break;
                    case "UART":
                        SerialPort?.Close();
                        ConnectState = false;
                        break;
                    case "GPIB":
                        throw new NotImplementedException();
                    case "USB":
                        throw new NotImplementedException();
                    default:
                        throw new NotImplementedException();
                }
                Timer.Stop();
            }
            else
            {
                //已经处于关闭状态,不进行操作
            }
        }

        public virtual int SendData(byte[] Data)
        {
            string SelectedCommunication = "";
            foreach (var temp in Config.CommunicationList)
            {
                if (temp.Selected)
                {
                    SelectedCommunication = temp.Name;
                }
            }
            if (ConnectState)
            {
                switch (SelectedCommunication.ToUpper())
                {
                    case "TCP":
                        stream.Write(Data, 0, Data.Length);
                        break;
                    case "UDP":
                        //UdpClient?.Send(Data, Data.Length, RemoteEndPoint);
                        UdpClient?.Send(Data, Data.Length);
                        break;
                    case "UART":
                        SerialPort?.Write(Data, 0, Data.Length);
                        break;
                    case "GPIB":
                        throw new NotImplementedException();
                    case "USB":
                        throw new NotImplementedException();
                    default:
                        throw new NotImplementedException();
                }
            }
            else
            {
                throw new Exception($"{Vender}_{Model}未连接!");
            }
            return 0;
        }

       
        #endregion


        
        public override int Enable(int AxisID)
        {
            string cmd = $"CONT1:AXIS({AxisID}):ENAB 1";
            SendData(System.Text.Encoding.ASCII.GetBytes(cmd)) ;
            return 0;

        }
        public override int Disable(int AxisID)
        {
            string cmd = $"CONT1:AXIS({AxisID}):ENAB 0";
            SendData(System.Text.Encoding.ASCII.GetBytes(cmd));
            return 0;


        }
        public override int Run(int AxisID, double Position, double Speed, double Acc, double Dcc, bool AbsoluteMovement = true)
        {
            string cmd = $"CONT1:AXIS({AxisID}):POS:COMM {Position}";
            SendData(System.Text.Encoding.ASCII.GetBytes(cmd));
            Thread.Sleep(10);
            cmd = $"CONT1:AXIS({AxisID}):VEL:SLEW {Speed}";
            SendData(System.Text.Encoding.ASCII.GetBytes(cmd));
            Thread.Sleep(10);
            cmd = $"CONT1:AXIS({AxisID}):MOT:STAR";
            SendData(System.Text.Encoding.ASCII.GetBytes(cmd));
            return 0;

        }

        public override int Stop(int AxisID)
        {
            string cmd = $"CONT1:AXIS({AxisID}):MOT:STOP";
            SendData(System.Text.Encoding.ASCII.GetBytes(cmd));
            Thread.Sleep(50);
            SendData(System.Text.Encoding.ASCII.GetBytes(cmd));
            return 0;
        }

        public override void ReSet()
        {
            throw new NotImplementedException();
        }

        public override bool ReachedState(int AxisID)
        {
            throw new NotImplementedException();
        }

        public override int TriggerOpen(int AxisID, double StartPosition, double EndPosition, double Interval, int PuslseWidth_us)
        {
            throw new NotImplementedException();

        }

        public override int TriggerClose(int AxisID)
        {
            return 0;

        }

        public override int TriggerOne(int AxisID)
        {
            throw new NotImplementedException();

        }
    }


}
